﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;

namespace FanaticInstaller.Controls
{
    public class SlideImageContainer : FrameworkElement
    {
        #region const

        public const int AnimationInterval = 1500;

        #endregion

        #region fields

        private bool _isSliding = false;
        private List<Image> _images = new List<Image>();
        private Image _primaryImage;
        private Image _enterImage;

        #endregion

        #region ctors


        public SlideImageContainer()
        {
            SizeChanged += SlideImageContainer_SizeChanged;
        }

        private void SlideImageContainer_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            foreach (var image in _images)
            {
                image.Width = e.NewSize.Width;
                image.Height = e.NewSize.Height;
                image.Arrange(new Rect(e.NewSize));
            }
        }

        #endregion

        #region overrides


        protected override Size ArrangeOverride(Size finalSize)
        {
            return base.ArrangeOverride(finalSize);
        }

        protected override int VisualChildrenCount => _images.Count;

        protected override Visual GetVisualChild(int index)
        {
            return _images[index];
        }

        #endregion

        #region methods

        private void AddVisual(Image visual)
        {
            _images.Add(visual);
            AddVisualChild(visual);
        }

        private void RemoveVisual(Image visual)
        {
            _images.Remove(visual);
            RemoveVisualChild(visual);
        }

        public void InitImage(Uri uri)
        {
            if (_isSliding) return;

            var initImage = CreateImage(uri);
            AddVisual(initImage);
            _primaryImage = initImage;
        }

        public void PushFromLeft(Uri uri)
        {
            if (_isSliding) return;

            _isSliding = true;
            var leftImage = CreateImage(uri);
            var trans = GetTranslateTransform(leftImage);
            trans.X = -ActualWidth;
            AddVisual(leftImage);

            _enterImage = leftImage;

            BeginXAnimation(leftImage, 0d);
            BeginXAnimation(_primaryImage, ActualWidth);

            var task = new Task(() =>
            {
                Thread.Sleep(AnimationInterval);
                Application.Current.Dispatcher.Invoke(new Action(ReplaceEnterImageToPrimaryImage));
                _isSliding = false;
            });
            task.Start();
        }


        public void PushFromRight(Uri uri)
        {
            if (_isSliding) return;

            _isSliding = true;
            var rightImage = CreateImage(uri);
            var trans = GetTranslateTransform(rightImage);
            trans.X = ActualWidth;
            AddVisual(rightImage);

            _enterImage = rightImage;
            BeginXAnimation(_primaryImage, -ActualWidth);

            BeginXAnimation(rightImage, 0d);

            var task = new Task(() =>
            {
                Thread.Sleep(AnimationInterval);
                Application.Current.Dispatcher.Invoke(new Action(ReplaceEnterImageToPrimaryImage));
                _isSliding = false;
            });
            task.Start();
        }

        private void ReplaceEnterImageToPrimaryImage()
        {
            RemoveVisual(_primaryImage);
            _primaryImage = _enterImage;
            _enterImage = null;
        }

        private void BeginXAnimation(Image image, double toValue)
        {
            if (image == null) return;
            var anim = new DoubleAnimation()
            {
                To = toValue,
                Duration = new Duration(TimeSpan.FromMilliseconds(AnimationInterval))
            };
            anim.EasingFunction = new QuarticEase() { EasingMode = EasingMode.EaseOut};
            var trans = GetTranslateTransform(image);
            trans.BeginAnimation(TranslateTransform.XProperty, anim);
        }

        ///<summary>创建图片。</summary>
        private Image CreateImage(Uri uri)
        {
            var newImage = new Image() { Source = new BitmapImage(uri), Stretch = Stretch.UniformToFill };
            newImage.Arrange(new Rect() { Width = ActualWidth, Height = ActualHeight });
            newImage.RenderTransform = new TranslateTransform();
            return newImage;
        }

        private TranslateTransform GetTranslateTransform(Image image)
        {
            return image.RenderTransform as TranslateTransform;
        }

        #endregion





    }
}
